#include "src/TGPoint.h"
#include <opencv2/core.hpp>
#include <benchmark/benchmark.h>

using namespace std;

const int MAXN = 10000;

void generateRandomPointSet(int n, cv::RNG& rng, std::vector<TGPoint>& dst) {
    dst.clear();
    dst.reserve(n);
    for(int i = 0; i < n; i ++) {
        dst.emplace_back(rng.uniform(0,10)*100.0, rng.uniform(0,10)*100.0);
    }
}


static void testDivideAndConquer(benchmark::State& state) {
    cv::RNG rng(0);
    for(auto _ : state) {
        vector<TGPoint> pts;
        pair<TGPoint, TGPoint> ret;
        double d = INT32_MAX;
        state.PauseTiming();
        generateRandomPointSet(MAXN, rng, pts);
        state.ResumeTiming();
        nearestPairWithDivideAndConquer(pts, ret);
    }
}

/*
规模: 100,00
包含生成数据时间:   7,765,452ns
不包含生成数据时间: 7,414,628ns
*/
BENCHMARK(testDivideAndConquer);

static void testBruteForce(benchmark::State& state) {
    cv::RNG rng(0);
    auto f = [](vector<TGPoint>& pts, pair<TGPoint, TGPoint>& ret, double& d)->void {
        int n = pts.size();
        for(int i = 0; i < n; i ++) {
            for(int j = 0; j < i; j ++) {
                double curd = pdist(pts[i], pts[j]);
                if(curd < d) {
                    d = curd;
                    ret.first = pts[i];
                    ret.second = pts[j];
                }
            }
        }
    };
    for(auto _ : state) {
        vector<TGPoint> pts;
        pair<TGPoint, TGPoint> ret;
        double d = INT32_MAX;
        state.PauseTiming();
        generateRandomPointSet(MAXN, rng, pts);
        state.ResumeTiming();
        f(pts, ret, d);
    }
}

/*
规模: 100,00
包含生成数据时间:   1,049,740,300 ns
不包含生成数据时间: 1,047,991,800 ns
*/
BENCHMARK(testBruteForce);


BENCHMARK_MAIN();